//
// Created by Administrator on 2021/11/26.
//

#ifndef LEARN_CPP_PSTASH_H
#define LEARN_CPP_PSTASH_H

#include <cassert>
#include <memory>

template<typename T, int inc = 10>
class PStash
{
public:
    PStash() : quantity{0}, next{0}, storage{nullptr} {};
    ~PStash();
    int Add(T* element);
    T* Remove(int index);
    T* operator [] (int index) const;
    int Count() const { return next; }

private:
    void Inflate(int increase = inc);
    int quantity;
    int next;
    T** storage;
};

template<typename T, int inc>
PStash<T, inc>::~PStash()
{
    for(int i = 0; i < next; ++i)
    {
        delete storage[i];
        storage[i] = nullptr;
    }

    delete []storage;
}

template<typename T, int inc>
int PStash<T, inc>::Add(T *element)
{
    if(next >= quantity)
    {
        Inflate(inc);
    }
    storage[next++] = element;
    return next - 1;
}

template<typename T, int inc>
T* PStash<T, inc>::Remove(int index)
{
    T* val = operator[](index);
    storage[index] = nullptr;
    return val;
}

template<typename T, int inc>
T* PStash<T, inc>::operator[](int index) const
{
    assert(index > 0 && index < next);
    return storage[index];
}

template<typename T, int inc>
void PStash<T, inc>::Inflate(int increase)
{
    const int psz = sizeof(T*);
    T** tmp = new T*[(quantity + increase) * psz];
    memset(tmp, 0, quantity + increase);
    memcpy(tmp, storage, quantity * psz);
    quantity += increase;
    delete []storage;
    storage = tmp;
}

#endif //LEARN_CPP_PSTASH_H
